package org.epidroid.epidroid.androsoul.ui.contactimport;

import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.epidroid.epidroid.R;
import org.epidroid.epidroid.androsoul.engine.AndroSoul;
import org.epidroid.epidroid.androsoul.engine.contacts.ContactGroup;
import org.epidroid.epidroid.androsoul.engine.contacts.NetsoulContact;
import org.epidroid.epidroid.androsoul.engine.service.AndroSoulService;
import org.epidroid.epidroid.androsoul.engine.service.AndroSoulServiceBinder;
import org.epidroid.epidroid.androsoul.engine.service.IAndroSoulService;
import org.epidroid.epidroid.androsoul.ui.utils.ContactsLoader;
import org.epidroid.epidroid.utils.Utils;

import android.app.ListActivity;
import android.app.ProgressDialog;
import android.content.ComponentName;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.DialogInterface.OnCancelListener;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.os.IBinder;
import android.provider.ContactsContract;
import android.provider.ContactsContract.Contacts;
import android.provider.ContactsContract.CommonDataKinds.Email;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;

/*
 * TODO:
 * - Display a message when no contacts have been found
 * - Display a loading toast during the loading of the contacts
 * - Implement the select all and select all buttons
 */
public class ContactsImportActivity extends ListActivity {

	private ArrayList<ContactImportItem> _list = null;

	// TODO: handle other emails from the Ionis group
	private static Pattern _emailRegExp = Pattern
			.compile("^(\\S+_\\S+)@epita.fr$");
	private ContactImportAdapter _adapter = null;
	// AndroSoul service
	IAndroSoulService _service = null;
	ProgressDialog _progressDialog = null;
	View _viewNoContacts = null;

	ServiceConnection _serviceConnection = null;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);

		showProgressDialog();

		_list = new ArrayList<ContactImportItem>();

		bindService();
	}

	@Override
	protected void onDestroy() {

		unbindService(_serviceConnection);

		super.onDestroy();
	}

	private void showProgressDialog() {
		_progressDialog = ProgressDialog.show(this, "",
				getString(R.string.importing_contacts), true);
		_progressDialog.setCancelable(true);
		_progressDialog.setOnCancelListener(new OnCancelListener() {

			@Override
			public void onCancel(DialogInterface dialog) {
				// TODO
			}

		});
	}

	private void hideProgressDialog() {
		_progressDialog.dismiss();
	}

	private Matcher isNetsoul(String email) {
		Matcher match = _emailRegExp.matcher(email);
		if (!match.find()) {
			return null;
		}
		return match;
	}

	private void bindService() {
		Intent intent = new Intent(this, AndroSoulService.class);
		_serviceConnection = new ServiceConnection() {
			public void onServiceConnected(ComponentName name,
					IBinder servicebinder) {
				IAndroSoulService service = ((AndroSoulServiceBinder) servicebinder)
						.getService();
				_service = service;

				launchThreadGetEmails();

			}

			public void onServiceDisconnected(ComponentName name) {
			}
		};
		bindService(intent, _serviceConnection, Context.BIND_AUTO_CREATE);
	}

	private Boolean alreadyAdded(String login) {
		/*
		 * TODO: the getContactFromName does not return null if the contact is
		 * not in the contacts list but has sent a message during the current
		 * session. (indeed, a contact is created in this case). So we have to
		 * make sure the contact does not belong to a group
		 */

		return (null != _service.getContactFromName(login));
	}

	private void launchThreadGetEmails() {
		Thread t = new Thread(new Runnable() {

			@Override
			public void run() {
				// Loading the contacts
				getEmails();
				Log.v(AndroSoul.LOGCAT, "DONE");
				ContactsImportActivity.this.runOnUiThread(new Runnable() {
					@Override
					public void run() {
						ContactsImportActivity.this.updateAdapter();
						hideProgressDialog();
					}
				});
			}

		});
		t.start();
	}

	private void updateAdapter() {

		setContentView(R.layout.androsoul_contact_import);

		_adapter = new ContactImportAdapter(ContactsImportActivity.this,
				R.layout.androsoul_message_item, _list);

		setListAdapter(_adapter);

		Log.v(AndroSoul.LOGCAT, "CONTACTS: " + _list.size());

		_viewNoContacts = findViewById(R.id.text_import_contact_no_contact);

		if (_list.isEmpty()) {
			_viewNoContacts.setVisibility(View.VISIBLE);
			getListView().setVisibility(View.GONE);
		} else {
			_viewNoContacts.setVisibility(View.GONE);
			getListView().setVisibility(View.VISIBLE);
		}

	}

	private void getEmails() {
		String[] t = new String[] {
				android.provider.ContactsContract.Contacts._ID,
				Contacts.DISPLAY_NAME, Email.DATA,
				ContactsContract.Contacts.PHOTO_ID };

		Cursor cursor = getContentResolver().query(Email.CONTENT_URI, t, null,
				null, null);

		Log.v(AndroSoul.LOGCAT, "CONTACTS: " + cursor.getCount());
		if (!cursor.moveToFirst())
			return;
		while (!cursor.isAfterLast()) {
			String name = cursor.getString(cursor
					.getColumnIndex(Contacts.DISPLAY_NAME));
			String email = cursor.getString(cursor.getColumnIndex(Email.DATA));
			long contact_id = cursor
					.getLong(cursor
							.getColumnIndex(android.provider.ContactsContract.Contacts._ID));
			long photo_id = cursor.getLong(cursor
					.getColumnIndex(ContactsContract.Contacts.PHOTO_ID));

			Matcher match = isNetsoul(email);
			if (null != match) {
				Log.v(AndroSoul.LOGCAT, "name = " + name + ", email = " + email
						+ ", photo = " + photo_id);
				String login = match.group(1);

				if (!alreadyAdded(login)) {
					Bitmap b = null;
					if (photo_id != 0) {
						Log.v(AndroSoul.LOGCAT, "trying to find photo id = "
								+ photo_id);

						b = Utils.loadContactPhoto(getContentResolver(),
								contact_id, photo_id);
						Log.v(AndroSoul.LOGCAT, "bitmap = " + (b == null));
					}

					ContactImportItem new_ = new ContactImportItem(login, name,
							b);
					if (null != b) {
						new_.setPhoneContactId(contact_id);
						new_.setPhonePhotoId(photo_id);
					}
					if (!_list.contains(new_))
						_list.add(new_);

				}
			}
			cursor.moveToNext();
		}
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		MenuInflater inflater = getMenuInflater();
		inflater.inflate(R.menu.androsoul_contact_import_menu, menu);
		return true;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see android.app.Activity#onOptionsItemSelected(android.view.MenuItem)
	 * Show the button that enables the user to send a wizz
	 */
	public boolean onOptionsItemSelected(MenuItem item) {
		switch (item.getItemId()) {
		case R.id.b_import_contact_import:
			processImport();
			break;
		default:
			break;
		}
		return true;
	}

	private void processImport() {

		// Add the contacts in the first group
		// TODO: add the possibility to chose the group in which the contact is
		// added
		ContactGroup group = _service.getGroupsList().get(0);
		if (null == group) {
			// WTF
			return;
		}

		List<String> contacts = new ArrayList<String>();
		for (ContactImportItem e : _list) {
			if (e.isSelected()) {
				NetsoulContact c = _service.addContact(e.get_login(), group);
				c.setPhoneContactId(e.getPhoneContactId());
				c.setPhonePhotoId(e.getPhonePhotoId());
			}
		}

		_service.addContacts(contacts, group);
		ContactsLoader.saveContacts(_service, this);

		this.finish();
	}
}
